package com.settlement.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.settlement.system.common.constant.SystemConstants;
import com.settlement.system.common.enums.DataGenerationEnum;
import com.settlement.system.common.result.Result;
import com.settlement.system.common.util.StringUtils;
import com.settlement.system.mapper.SysBaseColumnMatchMapper;
import com.settlement.system.mapper.SysCalculateColumnMapper;
import com.settlement.system.mapper.SysColumnMatchConditionMapper;
import com.settlement.system.model.entity.SysBaseColumnMatch;
import com.settlement.system.model.entity.SysCalculateColumn;
import com.settlement.system.model.entity.SysColumnMatchCondition;
import com.settlement.system.model.form.BaseColumnForm;
import com.settlement.system.model.form.ColumnMatchConditionForm;
import com.settlement.system.model.vo.TmBillConfigConditionImportVo;
import com.settlement.system.model.vo.TmBillConfigImportVo;
import com.settlement.system.service.SnowflakeIdWorker;
import com.settlement.system.service.SysBaseColumnMatchService;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 基础字段配置 服务实现类
 * </p>
 *
 * @author huangrensen
 * @since 2023-09-20
 */
@Service
@RequiredArgsConstructor
public class SysBaseColumnMatchServiceImpl extends ServiceImpl<SysBaseColumnMatchMapper, SysBaseColumnMatch> implements SysBaseColumnMatchService {

    private final Logger logger = LoggerFactory.getLogger(SysBaseColumnMatchServiceImpl.class);

    private final SysColumnMatchConditionMapper sysColumnMatchConditionMapper;

    private final SysCalculateColumnMapper sysCalculateColumnMapper;

    private final RedisTemplate redisTemplate;

    private final SnowflakeIdWorker snowflakeIdWorker = SnowflakeIdWorker.getInstance();

    @Override
    @SuppressWarnings("unchecked")
    public String saveForm(BaseColumnForm baseColumnForm) {
        SysBaseColumnMatch baseColumnMatch;
        boolean needCreate = false;
        if (StringUtils.hasText(baseColumnForm.getId())) {
            baseColumnMatch = this.getById(baseColumnForm.getId());
        } else {
            baseColumnMatch = new SysBaseColumnMatch();
            baseColumnMatch.setId(snowflakeIdWorker.nextId("BCM"));
            needCreate = true;
        }
        BeanUtil.copyProperties(baseColumnForm, baseColumnMatch);
        // 删除旧的符合条件
        sysColumnMatchConditionMapper.delete(new LambdaQueryWrapper<SysColumnMatchCondition>().eq(SysColumnMatchCondition::getMatchId, baseColumnForm.getId()));
        // 新增新的符合条件
        for (ColumnMatchConditionForm columnMatchConditionForm : baseColumnForm.getConditionFormList()) {
            SysColumnMatchCondition condition = new SysColumnMatchCondition();
            BeanUtil.copyProperties(columnMatchConditionForm, condition, "id");
            condition.setMatchId(baseColumnForm.getId());
            sysColumnMatchConditionMapper.insertData(condition);
        }
        // 保存或者更新
        if (needCreate) {
            this.baseMapper.insertData(baseColumnMatch);
        } else {
            this.baseMapper.update(baseColumnMatch);
        }
        // 删除缓存
        redisTemplate.delete(SystemConstants.BASE_COLUMN_CONFIG_PREFIX + baseColumnMatch.getPlatformKey());
        return baseColumnMatch.getId();
    }

    @Override
    @SuppressWarnings("unchecked")
    public boolean deleteMatch(String idsStr) {
        Assert.isTrue(StrUtil.isNotBlank(idsStr), "删除的数据为空");
        List<Long> ids = Arrays.stream(idsStr.split(",")).map(Long::parseLong).collect(Collectors.toList());
        List<SysBaseColumnMatch> list = this.list(new LambdaQueryWrapper<SysBaseColumnMatch>()
                .in(SysBaseColumnMatch::getId, ids));
        // 删除缓存
        for (SysBaseColumnMatch baseColumnMatch : list) {
            redisTemplate.delete(SystemConstants.BASE_COLUMN_CONFIG_PREFIX + baseColumnMatch.getPlatformKey());
        }
        return this.removeByIds(ids);
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<SysBaseColumnMatch> getByPlatform(String platformKey) {
        // 先从缓存取值
        Object value = redisTemplate.opsForValue().get(SystemConstants.BASE_COLUMN_CONFIG_PREFIX + platformKey);
        if (value != null) {
            // 直接返回
            return (List<SysBaseColumnMatch>) value;
        }
        List<SysBaseColumnMatch> list = this.list(new LambdaQueryWrapper<SysBaseColumnMatch>()
                .eq(SysBaseColumnMatch::getPlatformKey, platformKey));
        for (SysBaseColumnMatch sysBaseColumnMatch : list) {
            if (DataGenerationEnum.CALCULATE.getValue().equals(sysBaseColumnMatch.getDataGeneration())) {
                sysBaseColumnMatch.setBillType(null);
            }
            // 当数据类型为【通过计算】时，需要查出相关配置
            if (DataGenerationEnum.CALCULATE.getValue().equals(sysBaseColumnMatch.getDataGeneration())) {
                List<SysCalculateColumn> calculateColumnList = sysCalculateColumnMapper.selectList(new LambdaQueryWrapper<SysCalculateColumn>().eq(SysCalculateColumn::getLinkId, sysBaseColumnMatch.getId()));
                List<SysColumnMatchCondition> conditionList;
                for (SysCalculateColumn calculateColumn : calculateColumnList) {
                    // 符合条件
                    SysColumnMatchCondition condition = new SysColumnMatchCondition();
                    condition.setMatchId(calculateColumn.getId());
                    conditionList = sysColumnMatchConditionMapper.getList(condition);
                    calculateColumn.setConditions(conditionList);
                }
                sysBaseColumnMatch.setCalculateColumnList(calculateColumnList);
            } else {
                // 符合条件
                SysColumnMatchCondition condition = new SysColumnMatchCondition();
                condition.setMatchId(sysBaseColumnMatch.getId());
                List<SysColumnMatchCondition> conditionList = sysColumnMatchConditionMapper.getList(condition);
                sysBaseColumnMatch.setConditions(conditionList);
            }
        }
        // 加入缓存
        redisTemplate.opsForValue().set(SystemConstants.BASE_COLUMN_CONFIG_PREFIX + platformKey, list, 1, TimeUnit.HOURS);
        return list;
    }

    @Override
    public Result<String> check(String platformKey) {
        List<SysBaseColumnMatch> columnMatchList = this.list(new LambdaQueryWrapper<SysBaseColumnMatch>().eq(SysBaseColumnMatch::getPlatformKey, platformKey));
        if(columnMatchList.size()  == 0){
            if(platformKey.endsWith("bill")){
                return Result.failed("每个平台必须允许配置且一个【关联单号】和【业务日期】的对应关系");
            }else if(platformKey.endsWith("order")){
                return Result.failed("每个平台必须允许配置且一个【业务日期】的对应关系");
            }else if(platformKey.equalsIgnoreCase("omsOrder") || platformKey.equalsIgnoreCase("omsReturnOrder")){
                return Result.failed("必须允许配置且一个【业务日期】和【唯一标识】的对应关系");
            }
        }
        // 检查是否都存在关联单号和业务日期的字段配置
        if (platformKey.endsWith("bill") && columnMatchList.stream().noneMatch(sysBaseColumnMatch -> SystemConstants.LINK_NO.equals(sysBaseColumnMatch.getStandardColumn()))) {
            logger.error("每个平台必须允许配置且一个【关联单号】的对应关系");
            return Result.failed("每个平台必须允许配置且一个【关联单号】的对应关系");
        }
        // 只允许一个业务日期
        if (columnMatchList.stream().filter(sysBaseColumnMatch -> SystemConstants.BUSINESS_DATE.equals(sysBaseColumnMatch.getStandardColumn())).count() != 1) {
            logger.error("每个平台必须允许配置且一个【业务日期】的对应关系");
            return Result.failed("每个平台必须允许配置且一个【业务日期】的对应关系");
        }
        if (platformKey.equalsIgnoreCase("omsOrder") || platformKey.equalsIgnoreCase("omsReturnOrder")) {
            // 如果是OMS订单或者售后单，必须配置一个【唯一标识】的对应关系
            if (columnMatchList.stream().filter(sysBaseColumnMatch ->
                    SystemConstants.PLATFORM_UNIQUE_FLAG.equals(sysBaseColumnMatch.getStandardColumn())).count() != 1) {
                logger.error("必须配置一个【唯一标识】的对应关系");
                return Result.failed("必须配置一个【唯一标识】的对应关系");
            }
        }
        return Result.success();
    }

    @SuppressWarnings("unchecked")
    @Override
    public void saveConfig(List<TmBillConfigImportVo> vos, String platformKey) {
        // 清空缓存
        redisTemplate.delete(SystemConstants.BASE_COLUMN_CONFIG_PREFIX + platformKey);
        List<SysBaseColumnMatch> oldRecords = this.list(new LambdaQueryWrapper<SysBaseColumnMatch>().eq(SysBaseColumnMatch::getPlatformKey, platformKey));
        for (SysBaseColumnMatch oldRecord : oldRecords) {
            // 删除旧的符合条件
            sysColumnMatchConditionMapper.delete(new LambdaQueryWrapper<SysColumnMatchCondition>().eq(SysColumnMatchCondition::getMatchId, oldRecord.getId()));
            // 再查询通过计算的配置
            List<SysCalculateColumn> calculateColumnList = sysCalculateColumnMapper.selectList(new LambdaQueryWrapper<SysCalculateColumn>().eq(SysCalculateColumn::getLinkId, oldRecord.getId()));
            if (calculateColumnList.size() > 0) {
                for (SysCalculateColumn calculateColumn : calculateColumnList) {
                    // 删除旧的符合条件
                    sysColumnMatchConditionMapper.delete(new LambdaQueryWrapper<SysColumnMatchCondition>().eq(SysColumnMatchCondition::getMatchId, calculateColumn.getId()));
                }
            }
        }
        // 先删除旧的配置
        this.remove(new LambdaQueryWrapper<SysBaseColumnMatch>().eq(SysBaseColumnMatch::getPlatformKey, platformKey));
        List<SysColumnMatchCondition> matchConditions = new ArrayList<>();
        SysBaseColumnMatch sysBaseColumnMatch;
        SysCalculateColumn calculateColumn;
        SysColumnMatchCondition condition;
        for (TmBillConfigImportVo vo : vos) {
            sysBaseColumnMatch = new SysBaseColumnMatch();
            BeanUtil.copyProperties(vo, sysBaseColumnMatch);
            sysBaseColumnMatch.setId(snowflakeIdWorker.nextId("BCM"));
            // 平台
            sysBaseColumnMatch.setPlatformKey(platformKey);
            if(StringUtils.hasText(sysBaseColumnMatch.getBillType())){
                sysBaseColumnMatch.setBillType(sysBaseColumnMatch.getBillType().strip());
            }
            if (Objects.nonNull(sysBaseColumnMatch.getSourceColumn())) {
                sysBaseColumnMatch.setSourceColumn(sysBaseColumnMatch.getSourceColumn().strip());
            }
            sysBaseColumnMatch.setStandardColumn(sysBaseColumnMatch.getStandardColumn().strip());
            this.save(sysBaseColumnMatch);
            List<SysCalculateColumn> calculateColumnList = sysCalculateColumnMapper.selectList(new LambdaQueryWrapper<SysCalculateColumn>().eq(SysCalculateColumn::getLinkId,
                    sysBaseColumnMatch.getId()));
            for (SysCalculateColumn sysCalculateColumn : calculateColumnList) {
                // 删除缓存
                redisTemplate.delete(SystemConstants.BILL_COLUMN_CONDITION_PREFIX.formatted(sysCalculateColumn.getId()));
                sysCalculateColumnMapper.deleteById(sysCalculateColumn.getId());
            }
            // 过滤条件
            if (vo.getConfigConditionImportVoList() != null && vo.getConfigConditionImportVoList().size() > 0) {
                for (TmBillConfigConditionImportVo billConfigConditionImportVo : vo.getConfigConditionImportVoList()) {
                    condition = new SysColumnMatchCondition();
                    condition.setMatchId(sysBaseColumnMatch.getId());
                    condition.setConditions(billConfigConditionImportVo.getConditions().strip());
                    condition.setParams(billConfigConditionImportVo.getParams().strip());
                    matchConditions.add(condition);
                }
            }
            // 通过计算的配置
            if (vo.getCalculateConfigList() != null && vo.getCalculateConfigList().size() > 0) {
                for (TmBillConfigImportVo tmBillConfigImportVo : vo.getCalculateConfigList()) {
                    calculateColumn = new SysCalculateColumn();
                    calculateColumn.setId(snowflakeIdWorker.nextId("CC"));
                    calculateColumn.setLinkId(sysBaseColumnMatch.getId());
                    calculateColumn.setCalculateRule(tmBillConfigImportVo.getCalculateRule());
                    calculateColumn.setBillType(tmBillConfigImportVo.getBillType());
                    calculateColumn.setSourceColumn(tmBillConfigImportVo.getSourceColumn().strip());
                    sysCalculateColumnMapper.insertData(calculateColumn);
                    // 处理条件
                    if (tmBillConfigImportVo.getConfigConditionImportVoList() != null && tmBillConfigImportVo.getConfigConditionImportVoList().size() > 0) {
                        for (TmBillConfigConditionImportVo configConditionImportVo : tmBillConfigImportVo.getConfigConditionImportVoList()) {
                            condition = new SysColumnMatchCondition();
                            condition.setMatchId(calculateColumn.getId());
                            condition.setConditions(configConditionImportVo.getConditions().strip());
                            condition.setParams(configConditionImportVo.getParams().strip());
                            matchConditions.add(condition);
                        }
                    }
                }
            }
        }
        if (matchConditions.size() > 0) {
            matchConditions.forEach(sysColumnMatchConditionMapper::insertData);
        }
    }

    @Override
    public List<SysBaseColumnMatch> getBusinessConfigListByPlatform(String platformKey, String billType) {
        // 先从缓存那一次数据
        Object value = redisTemplate.opsForValue().get(SystemConstants.BASE_COLUMN_CONFIG_PREFIX + platformKey);
        List<SysBaseColumnMatch> columnMatchList;
        if(Objects.isNull(value)){
            columnMatchList = this.list(new LambdaQueryWrapper<SysBaseColumnMatch>().eq(SysBaseColumnMatch::getPlatformKey, platformKey));
            // 添加缓存
            redisTemplate.opsForValue().set(SystemConstants.BASE_COLUMN_CONFIG_PREFIX + platformKey, columnMatchList, 1, TimeUnit.HOURS);
        }else{
            columnMatchList = (List<SysBaseColumnMatch>) value;
        }
        if (Objects.nonNull(billType)) {
            return columnMatchList.stream().filter(item -> Objects.equals(item.getBillType(), billType) && Objects.equals(item.getStandardColumn(), SystemConstants.BUSINESS_DATE)).toList();
        } else {
            return columnMatchList.stream().filter(item -> Objects.equals(item.getStandardColumn(), SystemConstants.BUSINESS_DATE)).toList();
        }
    }

    @Override
    public List<SysBaseColumnMatch> getAllConfigListByPlatform(String platformKey) {
        // 先从缓存那一次数据
        Object value = redisTemplate.opsForValue().get(SystemConstants.BASE_COLUMN_CONFIG_PREFIX + platformKey);
        List<SysBaseColumnMatch> columnMatchList;
        if(Objects.isNull(value)){
            columnMatchList = this.list(new LambdaQueryWrapper<SysBaseColumnMatch>().eq(SysBaseColumnMatch::getPlatformKey, platformKey));
            // 添加缓存
            redisTemplate.opsForValue().set(SystemConstants.BASE_COLUMN_CONFIG_PREFIX + platformKey, columnMatchList, 1, TimeUnit.HOURS);
        }else{
            columnMatchList = (List<SysBaseColumnMatch>) value;
        }
        return columnMatchList;
    }

    @Override
    public List<SysBaseColumnMatch> getBusinessConfigListByPlatform(String platformKey) {
        return this.list(new LambdaQueryWrapper<SysBaseColumnMatch>().eq(SysBaseColumnMatch::getPlatformKey, platformKey).in(SysBaseColumnMatch::getStandardColumn, SystemConstants.BUSINESS_DATE, SystemConstants.OUT_BILL_DATE));
    }
}
